﻿
#include <iostream>
#include "../../xcom/xcom.hpp"

// 写盘线程1
int64_t g_w_speed = 0;//写盘速度  M/s
int64_t g_w_log_threshold = 100;// 耗时printf阈值 us

// 申请内存线程1
int64_t g_mem1_size = 10;// 每次申请内存 K
int64_t g_mem1_alloc_interval = 1000;// 每次sleep时间 ms
int64_t g_mem1_log_threshold = 0;// 耗时printf阈值 us

// 申请内存线程2
int64_t g_mem2_size = 500*1024;// 每次申请内存 K
int64_t g_mem2_alloc_interval = 10;// 每次sleep时间 ms
int64_t g_mem2_log_threshold = 1000*1000;// 耗时printf阈值 us

void get_para(int argc, char** argv,const char *key,int64_t &val)
{
    if(-1 != xx_get_argidx(argc,argv,key))
    {
        val = xx_get_arg_i64(argc,argv,key);
    }
    printf("[init]%s = %jd\n",key,val);
    
}
void do_para(int argc, char** argv)
{
    get_para(argc,argv,"-w_speed",g_w_speed);
    get_para(argc,argv,"-w_log_threshold",g_w_log_threshold);

    get_para(argc,argv,"-mem1_size",g_mem1_size);
    get_para(argc,argv,"-mem1_alloc_interval",g_mem1_alloc_interval);
    get_para(argc,argv,"-mem1_log_threshold",g_mem1_log_threshold);

    get_para(argc,argv,"-mem2_size",g_mem2_size);
    get_para(argc,argv,"-mem2_alloc_interval",g_mem2_alloc_interval);
    get_para(argc,argv,"-mem2_log_threshold",g_mem2_log_threshold);

    sleep_ms(1000);
}
///////////////////////////////////////////
void* fsm_mem(size_t size)
{
    void *p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) ;
    memset(p,0,size);
    return p;
}

void fsm_mem_thread(int64_t mem_size,int64_t alloc_interval,int64_t log_threshold)
{
    if(0 == mem_size)
        return ;

    printf("[thread start]fsm_file_thread tid=%u,mem_size=%jd,alloc_interval=%jd,log_threshold=%jd\n",
        this_thread::get_id(),mem_size,alloc_interval,log_threshold);

    while(true){
        auto begin = get_ns();

        printf("[mem in],size=%ju K\n",mem_size);
        void *p = fsm_mem(mem_size*1024);
        printf("[mem end],size=%ju K\n",mem_size);

        auto cost = get_ns() - begin;
        cost = cost / (1000);

        if(nullptr == p){
            X_P_INFO;
            continue;
        }

        if(cost >= log_threshold){
            printf("mem,size=%ju K, cost=%ju us\n",mem_size,cost);
        }

        munmap(p,mem_size*1024);
        sleep_ms(alloc_interval);
    }
}

void fsm_file_thread(int64_t w_speed,int64_t log_threshold)
{
    if(0 == w_speed)
        return ;

    printf("[thread start]fsm_file_thread tid=%u,w_speed=%jd,log_threshold=%jd\n",
        this_thread::get_id(),w_speed,log_threshold);

#define IOV_CNT 500
#define W_SIZE 1024

    uint64_t W_SPEED_SEC = w_speed*1024*1024;
    uint64_t w_cnt_sec = W_SPEED_SEC / (W_SIZE*IOV_CNT);
    uint64_t s_ns = X_NS_IN_SEC / w_cnt_sec;

    int fd = open("./fsm_temp",
            O_CREAT|O_RDWR|O_TRUNC,
            S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);

    char sz[W_SIZE] = {0};
    iovec vec[IOV_CNT]; 
    for(int i = 0 ;i < IOV_CNT;++i)
    {
        vec[i].iov_base = sz;
        vec[i].iov_len = W_SIZE;
    }

    while(true)
    {
        auto begin = get_ns();
        auto ret = writev(fd,vec,IOV_CNT);
        auto cost = get_ns() - begin;
        cost = cost / (1000);

        if(W_SIZE*IOV_CNT != ret)
        {
            printf("ret=%ju\n",ret);
            X_P_INFO;
        }
        if(cost >= log_threshold){
            printf("write file cost=%ju us\n",cost);
        }
        sleep_ns(s_ns);
    }
}

int main(int argc, char** argv)
{
    do_para(argc,argv);
    
    std::thread w(&fsm_file_thread,g_w_speed,g_w_log_threshold);
    std::thread m1(&fsm_mem_thread,g_mem1_size,g_mem1_alloc_interval,g_mem1_log_threshold);
    std::thread m2(&fsm_mem_thread,g_mem2_size,g_mem2_alloc_interval,g_mem2_log_threshold);

    w.join();
    m1.join();
    m2.join();
    return 0;
}


